#!/usr/bin/env python
# --*-- coding:utf-8 --*--
# author:g-y-b time:2020/5/25
from PyQt5.QtCore import QTimer, QCoreApplication
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog
from three import Ui_Form
import sys
import cv2
import numpy as np
import qimage2ndarray
import win32ui
import os


def hough(img, threshold):
    thetas = np.deg2rad(np.arange(0, 180, 2))
    row, cols = img.shape
    diag_len = np.ceil(np.sqrt(row ** 2 + cols ** 2))
    rhos = np.linspace(-diag_len, diag_len, int(2 * diag_len))
    cos_t = np.cos(thetas)
    sin_t = np.sin(thetas)
    num_theta = len(thetas)
    # 构造计数矩阵
    vote = np.zeros((int(2 * diag_len), num_theta), dtype=np.uint64)
    y_inx, x_inx = np.nonzero(img)
    # 计数
    for i in range(len(x_inx)):
        x = x_inx[i]
        y = y_inx[i]
        for j in range(num_theta):
            rho = round(x * cos_t[j] + y * sin_t[j]) + diag_len
            vote[int(rho), j] += 1

    # 拿到计数大于阈值的theta和rho
    indeies = np.argwhere(vote > threshold)
    rhos_idx = indeies[:, 0]
    theta_idx = indeies[:, 1]

    return vote, rhos[rhos_idx], thetas[theta_idx]


class three_ui(QMainWindow, Ui_Form):
    # 在实例化first类时，会自动调用它的初始化函数，因此，我们把想要让程序自动实现的程序功能都放在该函数下
    def __init__(self, parent=None):
        super(three_ui, self).__init__(parent)
        self.setupUi(self)
        self.CallBackFunctions()  # 各个控件背后的功能函数的集合，它定义了我们在程序界面上进行某项操作后实际执行的代码

        self.myImg = None
        self.edges = None
        self.pushButton_hough.setEnabled(False)
        self.pushButton_Canny.setEnabled(False)

    def CallBackFunctions(self):
        self.pushButton_Canny.clicked.connect(self.myCanny)
        self.pushButton_hough.clicked.connect(self.myHough)
        self.pushButton_ChooseImg.clicked.connect(self.ChooseImg)
        self.lineEdit_Canny_th1.returnPressed.connect(self.lineEdit_function)
        self.lineEdit_Canny_th2.returnPressed.connect(self.lineEdit_function)
        self.horizontalScrollBar1.sliderMoved.connect(self.horizontalScrollBar_Function)
        self.horizontalScrollBar2.sliderMoved.connect(self.horizontalScrollBar_Function)

    def lineEdit_function(self):
        self.horizontalScrollBar1.setValue(int(self.lineEdit_Canny_th1.text()))
        self.horizontalScrollBar2.setValue(int(self.lineEdit_Canny_th2.text()))
        self.myCanny()

    def horizontalScrollBar_Function(self):
        print(int(self.horizontalScrollBar1.value()))
        self.lineEdit_Canny_th1.setText(str(self.horizontalScrollBar1.value()))
        self.lineEdit_Canny_th2.setText(str(self.horizontalScrollBar2.value()))
        self.myCanny()

    def ChooseImg(self):
        dlg = win32ui.CreateFileDialog(1)
        # dlg.SetOFNInitialDir(r'D:\大三\大三下\计算机视觉\实验一\实验一（Python）\Img')
        dlg.DoModal()

        filename = dlg.GetPathName()
        print(filename)
        if filename == '':
            print("读取文件失败！")
        else:
            img = cv2.imread(filename)
            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转RGB
            self.myImg = img

            img = qimage2ndarray.array2qimage(img)  # 数组转QImage
            # 使图片适应label大小
            result = img.scaled(self.label_img.width(), self.label_img.height())
            self.label_img.setPixmap(QPixmap.fromImage(result))
            self.label_img.show()

        self.pushButton_hough.setEnabled(True)
        self.pushButton_Canny.setEnabled(True)

    def myCanny(self):
        gray = cv2.cvtColor(self.myImg, cv2.COLOR_RGB2GRAY)
        self.edges = cv2.Canny(gray, int(self.lineEdit_Canny_th1.text()), int(self.lineEdit_Canny_th2.text()))
        img = qimage2ndarray.array2qimage(self.edges)  # 数组转QImage
        # 使图片适应label大小
        result = img.scaled(self.label_img_Canny.width(), self.label_img_Canny.height())
        self.label_img_Canny.setPixmap(QPixmap.fromImage(result))
        self.label_img_Canny.show()

    def myHough(self):
        print("开始进行hough变换")
        print(int(self.lineEdit_hough_th.text()))
        self.myCanny()
        vote, rhos, thetas = hough(self.edges, int(self.lineEdit_hough_th.text()))
        # vote = np.uint8(vote.T)
        myImg = self.myImg.copy()
        for rho, theta in zip(rhos, thetas):
            x_center = self.myImg.shape[1] / 2
            x1 = int(x_center + 500)
            x2 = int(x_center - 500)
            a = np.sin(theta)
            b = np.cos(theta)
            if a == 0.0:
                a = 1e-5
            if b == 0.0:
                b = 1e-5
            y1 = int((rho - x1 * b) / a)
            y2 = int((rho - x2 * b) / a)
            cv2.line(myImg, (x1, y1), (x2, y2), (0, 255, 0), 2)

        img = qimage2ndarray.array2qimage(myImg)  # 数组转QImage
        # 使图片适应label大小
        result = img.scaled(self.label_img_hough.width(), self.label_img_hough.height())
        self.label_img_hough.setPixmap(QPixmap.fromImage(result))
        self.label_img_hough.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = three_ui()
    ui.show()
    sys.exit(app.exec_())
